home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Over 1,000 Windows 95 Programs
/
Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso
/
1138
/
source.zip
/
AREAS.C
next >
Wrap
C/C++ Source or Header
|
1995-02-11
|
11KB
|
461 lines
/* areas.c -- parse SOUP's AREAS file
This file is part of Paperboy, an offline mail/newsreader for Windows
Copyright (C) 1995 Michael H. Vartanian
vart@clark.net
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
#include <direct.h>
*/
#include "areas.h"
#include "soup.h"
#include "error.h"
#include "structs.h"
#include "msgs.h"
#include "reclaim.h"
static struct llareas * areahead=NULL; /* Top of all data structures */
char * packetpath=NULL;
char * errortext;
int DLLFUNC InitSOUPDLL ()
{
if (areahead!=NULL) reclaimareas(areahead);
areahead=NULL;
return 0;
}
int fgetlf (int max, FILE * stream, char * s)
{
int c=0;
char * p;
assert(stream!=NULL);
assert(s!=NULL);
assert(max>0);
/* If feof, return NULL */
if (feof(stream)) return 0;
/* Read in characters from stream until
a) LF character reached
b) EOF is reached
c) max-1 characters are read in
*/
p=s;
/* TODO: Optimize this function, since it's been profiled as > 50% of our CPU time! */
while ( (c!=LFCHAR) && !(feof(stream)) && ((p-s)<(max-1)) )
{
c=getc(stream);
*p++=(char)c;
}
/* Strip off LF, NULL terminate the string */
if (c==LFCHAR) p--;
*p='\0'; /* Null terminate the string */
return strlen(s);
}
int savepath (const char * fname)
{
char * endofpath;
packetpath=strdup(fname);
if (packetpath==NULL) { errortext="savepath:Out of Memory"; return ERRMEM; }
endofpath=strrchr(packetpath,PATH_SEP);
if (endofpath==NULL) { errortext="savepath: Path has no slashes"; return ERRIO; }/* Path has no slashes? */
endofpath++;
*endofpath='\0'; /* NULL terminate after last slash */
return 0; /* Everything OK */
}
void areatype (char * encoding)
{
/* m?, M? and b? become ??m (private mail)
u?, B? and i? become ??n (public news)
everything else becomes ??u (unknown) */
char areatype;
if (encoding[3]=='\0') /* If we need to figure this out */
{
switch (encoding[0])
{
case MAILTYPE:
areatype=MAILTYPE;
break;
case MAILMMDF:
areatype=MAILTYPE;
break;
case BINMAIL:
areatype=MAILTYPE;
break;
case RNEWSTYPE:
areatype=NEWSTYPE;
break;
case BINNEWS:
areatype=NEWSTYPE;
break;
default:
areatype=UNKTYPE;
break;
}
encoding[2]=areatype;
}
}
static int comparearea (const void * a1, const void * a2)
{
struct llareas * p1, * p2;
struct llareas ** p;
assert(a1!=NULL);
assert(a2!=NULL);
p=(struct llareas **)a1;
p1=(struct llareas *)*p;
p=(struct llareas **)a2;
p2=(struct llareas *)*p;
assert(p1!=NULL);
assert(p2!=NULL);
assert(p1->magic==AREAMAGIC);
assert(p2->magic==AREAMAGIC);
if (p1->isfolder && !p2->isfolder) return -1;
if (!p1->isfolder && p2->isfolder) return 1;
return strcmp(p1->name,p2->name);
}
int sortareas(void)
/* Sort the areas, email first, alphabetically */
{
struct llareas ** areas;
struct llareas * cur;
int p, numareas;
unsigned int arraysize;
/* We create an array large enough to hold all the areas */
arraysize=sizeof(struct llareas)*GetNumAreas();
areas=(struct llareas **)malloc(arraysize);
if (areas==NULL) { errortext="sortareas: qsortarray"; return ERRMEM; }
memset(areas,0,sizeof(arraysize));
/* Stuff pointers into the array */
cur=areahead;
numareas=GetNumAreas();
for (p=0; p<numareas; p++)
{
assert(cur!=NULL);
assert(cur->magic==AREAMAGIC);
areas[p]=cur;
cur=cur->next;
}
/* Sort the array */
qsort(areas, numareas, sizeof(struct llareas *), comparearea);
/* Reassmeble the linked list */
areahead=areas[0];
for (p=0; p<numareas-1; p++)
areas[p]->next=areas[p+1];
areas[p]->next=NULL; /* End of list */
free(areas);
return 0;
}
int DLLFUNC LoadAreas (const char * areasfname)
{
int result;
int holderror;
struct llareas * cur;
holderror=0;
/* Save path for future use */
result=savepath(areasfname);
if (result) holderror=result;
/* Read through AREAS file, recording all pertinent information */
result=parseareas (areasfname);
if (result) holderror=result;
/* Figure out the message type from the encoding */
cur=areahead;
while (cur!=NULL)
{
areatype(cur->encoding);
cur=cur->next;
}
/* Sort areas */
result=sortareas();
if (result) holderror=result;
/* Load in message summaries from whatever index (or not) we can use */
cur=areahead;
while (cur!=NULL)
{
result=parsemsg (cur);
if (result) holderror=result;
cur=cur->next;
}
return holderror;
}
void DLLFUNC RemoveArea (char * foldername)
{
struct llareas * cur, * prev;
assert(foldername!=NULL);
/* See if a folder with that name already exists, delete if so */
/* Case 0,1 */
while ( areahead && (strcmp(areahead->name,foldername)==0) )
{
/* Remove from head of list */
cur=areahead;
areahead=areahead->next;
reclaimgroup(cur);
free(cur);
}
/* Case 2,3 */
prev=areahead;
while (prev!=NULL && prev->next!=NULL)
{
if (strcmp(prev->next->name,foldername)==0)
{
/* Remove from middle of list */
cur=prev->next;
prev->next=cur->next;
reclaimgroup(cur);
free(cur);
}
else prev=prev->next;
}
}
int DLLFUNC LoadFolder (char * foldername, char * folderfile, char * folderdesc)
{
struct llareas * cur;
int holderror,result;
holderror=0;
assert(foldername!=NULL);
assert(folderfile!=NULL);
assert(folderdesc!=NULL);
/* Delete if we've already used it */
RemoveArea(foldername);
/* Create new folder */
cur=(struct llareas *) malloc(sizeof(struct llareas));
if (cur==NULL) { errortext="LoadFolder: new folder"; return ERRMEM; }
memset(cur,0,sizeof(struct llareas)); /* Zero it out */
cur->magic=AREAMAGIC;
cur->isfolder=1;
/* Add new folder to top of arealist */
cur->next=areahead;
areahead=cur;
/* Add data to folder */
cur->head=NULL; /* No messages yet */
cur->name=strdup(foldername);
if (cur->name==NULL) { errortext="LoadFolder:foldername"; return ERRMEM; }
cur->prefix=strdup(folderfile);
if (cur->prefix==NULL) { errortext="LoadFolder:folderfile"; return ERRMEM; }
cur->desc=strdup(folderdesc);
if (cur->desc==NULL) { errortext="LoadFolder:folderdesc"; return ERRMEM; }
strcpy(cur->encoding,"bnm"); /* Binary mail, no index, private mail */
/* Sort areas */
result=sortareas();
if (result) holderror=result;
result=parsemsg(cur); /* Read in messages */
if (result) holderror=result;
return (holderror);
}
int parseareas (const char * areasfname)
{
FILE * fareas;
char * prefix, * name, * encode, * desc;
struct llareas * cur;
char line[MAXLINE];
char newprefix[MAXLINE];
/* Check for existence of file, return error if doesn't exist */
if (areasfname==NULL) { errortext="parseareas: areasfname NULL"; return ERRIO;}
fareas=fopen(areasfname,"rb"); /* MS-DOS C compilers like binary */
if (fareas==NULL) { errortext="parseareas: areasfname not found"; return ERRIO; }
/* Until EOF, read in each line of AREAS file, adding to top of linked list
Check for EOF
Get next line, terminated by LF
Extract prefix, Extract area name, Extract encoding,
Extract description, if exists
Add to end of linked list
*/
while (!feof(fareas))
{
fgetlf(sizeof(line)-1,fareas,line);
prefix=strtok(line,SOUPSEP);
name=strtok(NULL,SOUPSEP);
encode=strtok(NULL,SOUPSEP);
desc=strtok(NULL,SOUPSEP); /* NULL if not present */
/* Remaining fields we ignore */
/* If we don't get all valid fields, we skip this record */
if ( !prefix || !(*prefix) ) continue;
if ( !name || !(*name ) ) continue;
if ( !encode || !(*encode) ) continue;
if (strlen(encode)<2) continue; /* Need two valid characters */
/* Allocate and add to head of linked list */
cur=(struct llareas *)malloc(sizeof(struct llareas));
if (cur==NULL) { errortext="parseareas: head linked list"; return ERRMEM;}
memset(cur,0,sizeof(struct llareas)); /* Zero it out */
cur->magic=AREAMAGIC;
cur->next=areahead;
areahead=cur;
/* Put data into linked-list structure */
cur->head=NULL; /* No messages yet */
/* Create a fully qualified pathname for prefix */
assert(packetpath!=NULL);
strcpy(newprefix,packetpath);
strcat(newprefix,prefix);
strcat(newprefix,MSGEXT);
cur->prefix=strdup(newprefix);
if (cur->prefix==NULL) { errortext="parseareas: prefix"; return ERRMEM; }
cur->name=strdup(name);
if (cur->name==NULL) { errortext="parseareas: name"; return ERRMEM; }
if (desc!=NULL)
{
cur->desc=strdup(desc);
if (cur->desc==NULL) { errortext="parseareas: desc"; return ERRMEM; }
} else cur->desc=strdup(""); /* No description available */
strncpy(cur->encoding,encode,sizeof(cur->encoding)-1);
}
fclose(fareas);
return 0;
}
int DLLFUNC GetNumAreas (void)
{
/* Count number of nodes in linked list */
struct llareas * cur;
unsigned int count=0;
cur=areahead;
while (cur!=NULL)
{
cur=cur->next;
count++;
}
return count;
}
struct llareas * findarea (int index)
/* Goes to [index] entry in linked list */
{
struct llareas * cur;
int max;
int count=1;
assert(index>0);
max=GetNumAreas();
assert(index<=max);
cur=areahead;
while (cur!=NULL && count!=index)
{
cur=cur->next;
count++;
}
assert(cur!=NULL);
return cur;
}
int DLLFUNC IsFolder (int index)
{
struct llareas * cur;
cur=findarea(index);
return cur->isfolder;
}
char * DLLFUNC GetAreaName (int index)
{
struct llareas * cur;
/* Find node matching index */
cur=findarea(index);
return cur->name;
}
char * DLLFUNC GetAreaEncoding (int index)
{
struct llareas * cur;
/* Find node matching index */
cur=findarea(index);
return cur->encoding;
}
char * DLLFUNC GetAreaDesc (int index)
{
struct llareas * cur;
/* Find node matching index */
cur=findarea(index);
if (cur->desc) return cur->desc;
return "";
}
char * DLLFUNC GetErrorText (void)
{
if (errortext!=NULL) return errortext;
else return "No Error";
}